package com.yeyks.commonReference.service.hotel.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.yeyks.common.utils.FormatUtils;
import com.yeyks.commonReference.service.account.AccountInfoService;
import com.yeyks.commonReference.service.hotel.HotelAccountBillService;
import com.yeyks.commonReference.service.hotel.HotelAccountOverviewService;
import com.yeyks.commonReference.service.hotel.HotelInfoService;
import com.yeyks.hotel.dal.dao.HotelAccountBillMapper;
import com.yeyks.hotel.dal.domain.HotelAccountBill;
import com.yeyks.hotel.dal.domain.HotelAccountOverview;
import com.yeyks.hotel.dal.domain.HotelInfo;
import com.yeyks.order.dal.domain.OrderHead;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 酒店收入账单明细表 服务实现类
 *
 * @author shuai
 * @date 2019-07-08
 */
@Service
@Slf4j
public class HotelAccountBillServiceImpl extends ServiceImpl<HotelAccountBillMapper, HotelAccountBill> implements HotelAccountBillService {

    @Autowired
    private HotelAccountOverviewService hotelAccountOverviewService;
    @Autowired
    private HotelInfoService hotelInfoService;
    @Autowired
    private AccountInfoService accountInfoService;

    /**
     * 已完成订单新增酒店收入账单明细
     *
     * @param orderHeads
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertHotelAccountBill(List<OrderHead> orderHeads) {
        if (orderHeads == null || orderHeads.size() == 0) {
            return true;
        }
        //根据订单生成一个map集合，key为hotelId，value为酒店
        Map<Integer, HotelInfo> hotelInfoMap = getHotelInfoMap(orderHeads);
        for (OrderHead orderHead : orderHeads) {
            //判断如果已经发放佣金则不在发放
            HotelAccountBill hotelAccountBill = baseMapper.selectOne(new QueryWrapper<HotelAccountBill>()
                    .eq(HotelAccountBill.BIZ_NO, orderHead.getOrderNo())
                    .eq(HotelAccountBill.TYPE, HotelAccountBill.Type.IN.value())
                    .eq(HotelAccountBill.REMARK, HotelAccountBill.Type.IN.desc()).last("limit 1"));
            if (null != hotelAccountBill) {
                log.info("该订单已发放过佣金orderNo = {}", orderHead.getOrderNo());
                continue;
            }
            //获取平台抽成比例
            int yeyuRate = orderHead.getYeyuRate() == null ? 0 : orderHead.getYeyuRate();
            //判断酒店是否在免佣期，免佣期的话
            if (hotelInfoService.isInNoFeeDate(orderHead.getGmtCreate(), orderHead.getHotelId())) {
                yeyuRate = 0;
            }
            HotelInfo hotelInfo = hotelInfoMap.get(orderHead.getHotelId());
            if (null == hotelInfo) {
                log.info("c2b订单酒店不存在orderNo = {}", orderHead.getOrderNo());
                continue;
            }
            //给酒店发放金额
            Integer hotelAmount = FormatUtils.amountToRateV2(orderHead.getSnapshotOriginTotalFee(), 10000 - yeyuRate);
            saveAccount(orderHead, hotelAmount, hotelInfo.getOperatorId(), 5);
            //抽成比例不为0的话给代理发佣金
            if (0 != yeyuRate) {
                Integer commissionAmount = FormatUtils.amountToRateV2(orderHead.getSnapshotOriginTotalFee(), yeyuRate);
                Map<Integer, Integer> map = accountInfoService.selectExcludeParentIdAndTypeById(hotelInfo.getOperatorId());
                for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
                    if (1403 == entry.getKey()) {
                        continue;
                    }
                    //计算
                    Integer agentAmount = accountInfoService.selectByIdAndType(entry.getKey(), entry.getValue(), 1, commissionAmount);
                    saveAccount(orderHead, agentAmount, entry.getKey(), entry.getValue());
                }
            }
        }
        return true;
    }

    private void saveAccount(OrderHead orderHead, Integer amount, Integer accountId, Integer accountType) {
        Date date = new Date();
        HotelAccountBill hotelAccountBill = new HotelAccountBill();
        hotelAccountBill.setOperatorAmount(amount);
        hotelAccountBill.setBizNo(orderHead.getOrderNo());
        hotelAccountBill.setRemark(HotelAccountBill.Type.IN.desc());
        hotelAccountBill.setType(HotelAccountBill.Type.IN.value());
        hotelAccountBill.setCreateTime(date);
        hotelAccountBill.setHotelId(orderHead.getHotelId());
        hotelAccountBill.setAccountId(accountId);
        hotelAccountBill.setAccountType(accountType);
        //插入c2b佣金明细
        if (baseMapper.insert(hotelAccountBill) != 1) {
            log.info("c2b订单佣金详情写入失败orderNo = {}", orderHead.getOrderNo());
        }
        //订单的营业额
        int turnoverAmount = orderHead.getSnapshotOriginTotalFee() == null ? 0 : orderHead.getSnapshotOriginTotalFee();
        //更新账户信息
        updateAccountOverview(hotelAccountBill, turnoverAmount);
    }

    /**
     * 通过酒店id查询酒店账户总览表，以及更新酒店账户信息
     *
     * @param bill
     * @param turnoverAmount 营业额
     * @return
     */
    private void updateAccountOverview(HotelAccountBill bill, int turnoverAmount) {
        try {
            HotelAccountOverview overview = hotelAccountOverviewService.selectByAccountId(bill.getAccountId(), bill.getAccountType());
            overview.setTotalInAmount(overview.getTotalInAmount() + turnoverAmount);
            overview.setTotalFeeAmount(overview.getTotalFeeAmount() + bill.getOperatorAmount());
            overview.setRemainAmount(overview.getRemainAmount() + bill.getOperatorAmount());
            overview.setUpdateTime(new Date());
            if (!hotelAccountOverviewService.updateById(overview)) {
                log.info("c2b订单佣金写入失败orderNo = {}", bill.getBizNo());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据订单生成一个map集合，key为hotelId，value为酒店
     *
     * @param orderHeads
     * @return
     */
    private Map<Integer, HotelInfo> getHotelInfoMap(List<OrderHead> orderHeads) {
        if (null == orderHeads || orderHeads.size() == 0) {
            return Maps.newHashMap();
        }
        try {
            Set<OrderHead> set = new TreeSet<>(Comparator.comparing(OrderHead::getHotelId));
            set.addAll(orderHeads);
            List<OrderHead> collect = Lists.newArrayList(set);
            List<Integer> hotelIds = Lists.transform(collect, OrderHead::getHotelId);
            List<HotelInfo> hotelInfos = hotelInfoService.selectByIds(hotelIds);
            return Maps.uniqueIndex(hotelInfos, HotelInfo::getId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Maps.newHashMap();
    }
}
